package crud.server.util;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.Date;

import javax.persistence.Entity;

import com.google.gwt.user.client.rpc.IsSerializable;
import common.utils.BeanUtil;
import common.utils.StringUtil;

import crud.client.data.Colonne;
import crud.client.data.ColonneDate;
import crud.client.data.ColonneDouble;
import crud.client.data.ColonneDoubleToFloatDataConverter;
import crud.client.data.ColonneInteger;
import crud.client.data.ColonneLongToIntegerDataConverter;
import crud.client.data.ColonneString;
import crud.client.data.ColonneToOne;
import crud.client.factory.form.DateFormItemFactory;
import crud.client.factory.form.DoubleFormItemFactory;
import crud.client.factory.form.IntegerFormItemFactory;
import crud.client.factory.form.StringFormItemFactory;
import crud.client.factory.form.ToOneComboBoxFactory;
import crud.client.factory.list.grid.DateListGridFieldFactory;
import crud.client.factory.list.grid.DoubleListGridFieldFactory;
import crud.client.factory.list.grid.IntegerListGridFieldFactory;
import crud.client.factory.list.grid.StringListGridFieldFactory;
import crud.client.factory.list.grid.ToOneListGridFieldFactory;

public class DataConversionUtil
{
	public static Colonne newColonne(Field field)
	{
		if (BeanUtil.isToOne(field) == true)
		{
			ColonneToOne colonne = new ColonneToOne((IsSerializable) BeanUtil.newInstance(field.getType()));
			colonne.setFormItemFactory(new ToOneComboBoxFactory());
			colonne.setListGridFactory(new ToOneListGridFieldFactory());
			return colonne;
		}
		
		// Le type de la donnée
		if (Date.class.isAssignableFrom(field.getType()))
		{
			ColonneDate colonne = new ColonneDate();
			colonne.setFormItemFactory(new DateFormItemFactory());
			colonne.setListGridFactory(new DateListGridFieldFactory());
			return colonne;
		} else if (Integer.class.isAssignableFrom(field.getType()))
		{
			ColonneInteger colonne = new ColonneInteger();
			colonne.setFormItemFactory(new IntegerFormItemFactory());
			colonne.setListGridFactory(new IntegerListGridFieldFactory());
			return colonne;
		}else if (Long.class.isAssignableFrom(field.getType()))
		{
			ColonneInteger colonne = new ColonneInteger();
			colonne.setFormItemFactory(new IntegerFormItemFactory());
			colonne.setListGridFactory(new IntegerListGridFieldFactory());
			colonne.setDataConverter(new ColonneLongToIntegerDataConverter());
			return colonne;
		}
		else if (Double.class.isAssignableFrom(field.getType()))
		{
			ColonneDouble colonne = new ColonneDouble();
			colonne.setFormItemFactory(new DoubleFormItemFactory());
			colonne.setListGridFactory(new DoubleListGridFieldFactory());
			colonne.setDataConverter(new ColonneDoubleToFloatDataConverter());
			return colonne;
		}	else if (Float.class.isAssignableFrom(field.getType()))
		{
			ColonneDouble colonne = new ColonneDouble();
			colonne.setFormItemFactory(new DoubleFormItemFactory());
			colonne.setListGridFactory(new DoubleListGridFieldFactory());
			return colonne;
		}else if (String.class.isAssignableFrom(field.getType()))
		{
			ColonneString colonne = new ColonneString();
			colonne.setFormItemFactory(new StringFormItemFactory());
			colonne.setListGridFactory(new StringListGridFieldFactory());
			return colonne;
		} else
		{
			throw new RuntimeException("Type de champ non reconnu: " + field.getType() + ". Champ " + field.getDeclaringClass().getName() + "." + field.getName());
		}		
	}
	
	public static String donneeToString(Colonne colonne, Serializable donnee)
	{
		if (donnee == null)
		{
			return null;
		}
		
		// Un ComboBox Getter ??
//		if (colonne.getMultipleValueFormItem() != null)
//		{
//			return colonne.getMultipleValueFormItem().displayValue(simpleDonneeToString(colonne, donnee));
//		}
		
		// Le type de la donnée
		return simpleDonneeToString(colonne, donnee);
	}
	
	public static String donneeToKey(Object donnee)
	{
		if (donnee == null)
		{
			return null;
		}
		
		// Le type de la donnée
		if (Date.class.isAssignableFrom(donnee.getClass()))
		{
			return StringUtil.toString((Date) donnee);
		} else if (Integer.class.isAssignableFrom(donnee.getClass()))
		{
			return StringUtil.toString((Integer) donnee);
		} else if (Double.class.isAssignableFrom(donnee.getClass()))
		{
			return StringUtil.toString((Double) donnee);
		} else if (donnee.getClass().getAnnotation(Entity.class) != null)
		{
			String key = "";
			
			for (Field field : BeanUtil.getIdFields(donnee.getClass()))
			{
				key += donneeToKey(BeanUtil.getProperty(donnee, field.getName()));
			}
			return key;
		} else
		{
			return donnee.toString();
		} 	
	}
	

	private static String simpleDonneeToString(Colonne colonne, Serializable donnee)
	{
		if (donnee == null)
		{
			return null;
		}
		// Le type de la donnée
		if (Date.class.isAssignableFrom(donnee.getClass()))
		{
			return StringUtil.toString((Date) donnee);
		} else if (Integer.class.isAssignableFrom(donnee.getClass()))
		{
			return StringUtil.toString((Integer) donnee);
		} else if (Double.class.isAssignableFrom(donnee.getClass()))
		{
			return StringUtil.toString((Double) donnee);
		}
		else if (colonne.getDisplayValue() != null && colonne.getDisplayValue().isEmpty() == false) 
		{
			return StringUtil.interpretsSpecialString(colonne.getDisplayValue(), donnee);
		} else
		{
			return donnee.toString();
		} 		
	}
	

	public static Comparable<?> StringToDonnee(Colonne colonne, String donnee)
	{
		if (donnee == null || donnee.isEmpty())
		{
			return null;
		}
		// Le type de la donnée
		if (ColonneDate.class.isAssignableFrom(colonne.getClass()))
		{
			return StringUtil.toDate(donnee);
		} else if (Integer.class.isAssignableFrom(colonne.getClass()))
		{
			return StringUtil.toInt(donnee);
		} else if (Double.class.isAssignableFrom(colonne.getClass()))
		{
			return StringUtil.toDouble(donnee);
		}
		else
		{
			return donnee;
		} 		
	}
}
